package cn.xieyang.debugger;

public class TimeTrackingPacketSenderDebugger {

    public static void main(String[] args) {

    }

    public static boolean demo(byte[] packet, int packetLen) {
        while (true) {
            // 如果是条件断点的代码，直接退出，不记录。
            if (new String(packet).toLowerCase().contains("debugger_sql_record_detail_tbl")) {
                return false;
            }
            if (System.getProperties().put("customerKey#1", "1") != null) {
                // 注释掉线程让步
                // System.out.println("#01-SQL_LOG_MARKER\n" + "线程：[" + Thread.currentThread().getName() + "]，线程让步");
                Thread.yield();
                continue;
            }
            StringBuilder printResultSB = new StringBuilder();
            printResultSB.append("\n");
            String strRealSql = new String(packet,1,packetLen-1);
            String simpleSqlStr = strRealSql;
            String lowerSql = strRealSql.toLowerCase();
            // 是否是定时任务SQL
            Boolean isTimedTaskSql = lowerSql.contains("ACT_RU_JOB".toLowerCase());
            // 是否是系统SQL
            Boolean isSysSql = lowerSql.contains("@@".toLowerCase());
            String sqlType = null;
            if (lowerSql.trim().startsWith("SELECT".toLowerCase())) {
                sqlType = "SELECT";
            }
            if (lowerSql.trim().startsWith("UPDATE".toLowerCase())) {
                sqlType = "UPDATE";
            }
            if (lowerSql.trim().startsWith("INSERT".toLowerCase())) {
                sqlType = "INSERT";
            }
            if (lowerSql.trim().startsWith("DELETE".toLowerCase())) {
                sqlType = "DELETE";
            }
            Boolean isCRUDSql = sqlType != null;

            // 定时任务SQL不打印
            if(isTimedTaskSql) {
                // System.out.println("#01-SQL_LOG_MARKER\n" + "定时任务SQL不打印调用栈，SQL：\n" + strRealSql);
                System.getProperties().remove("customerKey#1");
                return false;
            }

            // 系统SQL不打印
            if(isSysSql) {
                // System.out.println("#01-SQL_LOG_MARKER\n" + "系统SQL不打印");
                System.getProperties().remove("customerKey#1");
                return false;
            }

            // 非业务SQL不打印
            if(!isCRUDSql) {
                // System.out.println("#01-SQL_LOG_MARKER\n" + "非业务SQL不打印");
                System.getProperties().remove("customerKey#1");
                return false;
            }

            StringBuilder stackSB = new StringBuilder();
            StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace();
            for (int i = stackTrace.length - 1; i >= 0; i--) {
                StackTraceElement ele = stackTrace[i];
                Boolean isPrint = ele.getClassName().contains("tansun");
                if (!isPrint) continue;
                stackSB.append(ele.getClassName()).append("#").append(ele.getMethodName())
                        .append("(").append(ele.getFileName()).append(":").append(ele.getLineNumber()).append(")")
                        .append("\n");
            }
            if (stackSB.length() == 0){
                stackSB.append("无符合条件调用栈").append("\n");
            }

            printResultSB.append("============================start================================").append("\n");
            printResultSB.append(strRealSql).append(";").append("\n");
            printResultSB.append("----------------------------------------------------------------").append("\n");
            printResultSB.append(java.time.LocalDateTime.now().format(java.time.format.DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSS")) + " 线程：[").append(Thread.currentThread().getName()).append("]，SQL类型：[").append(sqlType).append("]，调用栈：").append("\n");
            printResultSB.append(stackSB);
            printResultSB.append("============================end================================").append("\n");
            System.out.println("#01-SQL_LOG_MARKER\n" + printResultSB);
            String pid = "";
            try {
                String os = System.getProperty("os.name").toLowerCase();
                boolean isAppend = true;
                pid = java.lang.management.ManagementFactory.getRuntimeMXBean().getName().split("@")[0];

                String sqlStackPath = "";
                if (os.contains("win")) {
                    sqlStackPath = "D:/sql_stack_log_" + pid + "_" + java.time.LocalDate.now().format(java.time.format.DateTimeFormatter.ofPattern("yyyy-MM-dd")) + ".log";
                } else if (os.contains("linux")) {
                    sqlStackPath = "/home/xieyang/sql_stack_log_" + pid + "_" + java.time.LocalDate.now().format(java.time.format.DateTimeFormatter.ofPattern("yyyy-MM-dd")) + ".log";
                }
                java.io.File sqlStackFile = new java.io.File(sqlStackPath);
                if (!sqlStackFile.exists()) {
                    sqlStackFile.createNewFile();
                }
                java.io.BufferedWriter sqlStackWriter = new java.io.BufferedWriter(new java.io.OutputStreamWriter(new java.io.FileOutputStream(sqlStackFile, isAppend), java.nio.charset.StandardCharsets.UTF_8));
                try {
                    sqlStackWriter.write("#01-SQL_LOG_MARKER\n" + printResultSB.toString());
                    sqlStackWriter.flush();
                } catch (java.io.IOException e) {
                    // ignore
                } finally {
                    try {
                        sqlStackWriter.close();
                    } catch (Exception var2) {
                    }
                }
                String sqlPath = "";
                if (os.contains("win")) {
                    sqlPath = "D:/sql_log_" + pid + "_"  + java.time.LocalDate.now().format(java.time.format.DateTimeFormatter.ofPattern("yyyy-MM-dd")) + ".log";
                } else if (os.contains("linux")) {
                    sqlPath = "/home/xieyang/sql_log_" + pid + "_"  + java.time.LocalDate.now().format(java.time.format.DateTimeFormatter.ofPattern("yyyy-MM-dd")) + ".log";
                }
                java.io.File sqlFile = new java.io.File(sqlPath);
                if (!sqlFile.exists()) {
                    sqlFile.createNewFile();
                }
                java.io.BufferedWriter sqlWriter = new java.io.BufferedWriter(new java.io.OutputStreamWriter(new java.io.FileOutputStream(sqlFile, isAppend), java.nio.charset.StandardCharsets.UTF_8));
                try {
                    if ("SELECT".equals(sqlType)) {
                        int selectIndex = lowerSql.indexOf("select");
                        int fromIndex = lowerSql.indexOf("from");
                        // 确保SELECT在FROM之前
                        if (selectIndex >= 0 && fromIndex > selectIndex) {
                            // 找到SELECT和FROM的位置
                            String beforeSelect = strRealSql.substring(0, selectIndex);
                            String afterFrom = strRealSql.substring(fromIndex);
                            // 构建新的SQL
                            simpleSqlStr = beforeSelect + "SELECT * " + afterFrom;
                        }
                    }
                    sqlWriter.write(simpleSqlStr + ";\n");
                    sqlWriter.flush();
                } catch (java.io.IOException e) {
                    // ignore
                } finally {
                    try {
                        sqlWriter.close();
                    } catch (Exception var2) {
                    }
                }
            } catch (java.io.IOException e) {
                // ignore
            }
            // ========================================================SQL明细表========================================================
            try {
                java.sql.Connection conn = (java.sql.Connection)System.getProperties().get("customerKey#jdbcConn-ganjiang-db");
                if (java.util.Objects.isNull(conn)) {
                    // 建立数据库连接
                    conn = java.sql.DriverManager.getConnection("jdbc:mysql://192.168.196.3:3306/ganjiang-db", "root", "123456");
                    System.getProperties().put("customerKey#jdbcConn-ganjiang-db",conn);
                }

                String ip = "127.0.0.1";
                try {
                    java.util.Enumeration<java.net.NetworkInterface> interfaces = java.net.NetworkInterface.getNetworkInterfaces();
                    while (interfaces.hasMoreElements()) {
                        java.net.NetworkInterface iface = interfaces.nextElement();
                        // 跳过回环接口和未启用的接口
                        if (iface.isLoopback() || !iface.isUp()) {
                            continue;
                        }

                        java.util.Enumeration<java.net.InetAddress> addresses = iface.getInetAddresses();
                        while (addresses.hasMoreElements()) {
                            java.net.InetAddress addr = addresses.nextElement();
                            // 过滤IPv6地址和回环地址
                            if (addr.isLoopbackAddress() || addr.getHostAddress().contains(":")) {
                                continue;
                            }
                            // 返回找到的第一个非回环IPv4地址
                            ip = addr.getHostAddress();
                        }
                    }
                } catch (java.net.SocketException e) {
                    // ignore
                }
                // 表名
                String tblName = "";
                try {
                    String sql = strRealSql.trim();
                    if ("SELECT".equals(sqlType)) {
                        // 查找 FROM 关键字位置（不区分大小写）
                        int fromIndex = lowerSql.indexOf("from");
                        if (fromIndex == -1) throw new NullPointerException();

                        // 找到 FROM 后的第一个非空格字符
                        int tableStartIndex = -1;
                        for (int i = fromIndex + 4; i < sql.length(); i++) {
                            if (!Character.isWhitespace(sql.charAt(i))) {
                                tableStartIndex = i;
                                break;
                            }
                        }
                        if (tableStartIndex == -1) throw new NullPointerException();

                        // 找到表名的结束位置（第一个空格或语句结束）
                        int tableEndIndex = -1;
                        for (int i = tableStartIndex; i < sql.length(); i++) {
                            if (Character.isWhitespace(sql.charAt(i))) {
                                tableEndIndex = i - 1;
                                break;
                            }
                        }
                        if (tableEndIndex == -1) tableEndIndex = sql.length() - 1;

                        // 提取表名并去除反引号
                        String tableName = sql.substring(tableStartIndex, tableEndIndex + 1).trim();
                        tblName = tableName.replace("`", "");

                    } else if ("UPDATE".equals(sqlType)) {
                        // 查找 UPDATE 关键字位置（不区分大小写）
                        int updateIndex = lowerSql.indexOf("update");
                        if (updateIndex == -1) throw new NullPointerException();

                        // 找到 UPDATE 后的第一个非空格字符
                        int tableStartIndex = -1;
                        for (int i = updateIndex + 6; i < sql.length(); i++) {
                            if (!Character.isWhitespace(sql.charAt(i))) {
                                tableStartIndex = i;
                                break;
                            }
                        }
                        if (tableStartIndex == -1) throw new NullPointerException();

                        // 查找 SET 关键字位置（不区分大小写）
                        int setIndex = lowerSql.indexOf("set", tableStartIndex);
                        if (setIndex == -1) throw new NullPointerException();

                        // 提取表名并去除反引号
                        String tableName = sql.substring(tableStartIndex, setIndex).trim();
                        tblName = tableName.replace("`", "");

                    } else if ("INSERT".equals(sqlType)) {
                        // 查找 INTO 关键字位置（不区分大小写）
                        int intoIndex = lowerSql.indexOf("into");
                        if (intoIndex == -1) throw new NullPointerException();

                        // 找到 INTO 后的第一个非空格字符
                        int tableStartIndex = -1;
                        for (int i = intoIndex + 4; i < sql.length(); i++) {
                            if (!Character.isWhitespace(sql.charAt(i))) {
                                tableStartIndex = i;
                                break;
                            }
                        }
                        if (tableStartIndex == -1) throw new NullPointerException();

                        // 查找左括号位置
                        int parenIndex = sql.indexOf('(', tableStartIndex);
                        if (parenIndex == -1) throw new NullPointerException();

                        // 提取表名并去除反引号
                        String tableName = sql.substring(tableStartIndex, parenIndex).trim();
                        tblName = tableName.replace("`", "");

                    } else if ("DELETE".equals(sqlType)) {
                        // 查找 FROM 关键字位置（不区分大小写）
                        int fromIndex = lowerSql.indexOf("from");
                        if (fromIndex == -1) throw new NullPointerException();

                        // 找到 FROM 后的第一个非空格字符
                        int tableStartIndex = -1;
                        for (int i = fromIndex + 4; i < sql.length(); i++) {
                            if (!Character.isWhitespace(sql.charAt(i))) {
                                tableStartIndex = i;
                                break;
                            }
                        }
                        if (tableStartIndex == -1) throw new NullPointerException();

                        // 找到表名的结束位置（第一个空格或语句结束）
                        int tableEndIndex = -1;
                        for (int i = tableStartIndex; i < sql.length(); i++) {
                            if (Character.isWhitespace(sql.charAt(i))) {
                                tableEndIndex = i - 1;
                                break;
                            }
                        }
                        if (tableEndIndex == -1) tableEndIndex = sql.length() - 1;

                        // 提取表名并去除反引号
                        String tableName = sql.substring(tableStartIndex, tableEndIndex + 1).trim();
                        tblName = tableName.replace("`", "");

                    } else {
                        throw new NullPointerException();
                    }
                } catch (Exception e) {
                    // ignore
                }



                java.util.Map<String, String> colMap = new java.util.LinkedHashMap<>();
                // 明细编号
                colMap.put("detail_no", "'DTL" + java.util.UUID.randomUUID() + "'");
                // ip地址
                colMap.put("ip_address", "'" + ip + "'");
                // 进程号
                colMap.put("pid", "'" + pid + "'");
                // 线程名
                colMap.put("thread_name", "'" + Thread.currentThread().getName() + "'");
                // sql类型
                colMap.put("sql_type", "'" + sqlType + "'");
                // 表名
                colMap.put("tbl_name", "'" + tblName + "'");
                // 精简SQL内容
                colMap.put("simple_sql_content", "'" + simpleSqlStr.replaceAll("'","\\\\'") + "'");
                // 完整SQL
                colMap.put("full_sql_content", "'" + strRealSql.replaceAll("'","\\\\'") + "'");
                // 调用栈内容
                colMap.put("call_stack_content", "'" + stackSB + "'");
                // 时间戳
                colMap.put("timestamp_rcd", String.valueOf(System.currentTimeMillis()));

                java.sql.Statement stmt = conn.createStatement();
                StringBuilder insertSql = new StringBuilder();
                insertSql.append("insert into `ganjiang-db`.`debugger_sql_record_detail_tbl` ");
                insertSql.append("(");
                java.util.Iterator<String> colNameIterator = colMap.keySet().iterator();
                while (colNameIterator.hasNext()) {
                    String colName = colNameIterator.next();
                    insertSql.append("`" + colName + "`");
                    if (colNameIterator.hasNext()) insertSql.append(",");
                }
                insertSql.append(") values ");
                insertSql.append("(");
                java.util.Iterator<String> valIterator = colMap.values().iterator();
                while (valIterator.hasNext()) {
                    insertSql.append(valIterator.next());
                    if(valIterator.hasNext()) insertSql.append(",");
                }
                insertSql.append(");");
                // 执行SQL
//                System.out.println(insertSql.toString());
                stmt.executeUpdate(insertSql.toString());
            } catch (java.sql.SQLException e) {
                // ignore
                e.printStackTrace();
            }
            System.getProperties().remove("customerKey#1");
            return false;
        }
    }

}
